package cn.kduck;

import io.modelcontextprotocol.client.McpSyncClient;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import java.util.List;
import java.util.Scanner;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;

@SpringBootApplication
public class KduckAi {
    public static void main(String[] args) {
        SpringApplication.run(KduckAi.class,args);
    }

    @Bean
    public CommandLineRunner runner(ChatClient.Builder builder, List<McpSyncClient> mcpClients) {
        //🎬 示例1 等待模型返回所有内容后一次性返回
//        return args -> {
//            ChatClient chatClient = builder.build();
//            String response = chatClient.prompt("给我讲一个笑话").call().content();
//            System.out.println(response);
//        };

//        //🎬 示例2 采用流式返回模式
//        return args -> {
//            ChatClient chatClient = builder.build();
//            chatClient.prompt("给我讲一个笑话").stream()
//                    .content().subscribe(System.out::print);
//            //由于流式采用响应式编程，为异步执行。如果不堵塞住程序会直接结束，因此这里30秒后无论如何都会结束
//            Thread.sleep(30*1000);
//        };

        //🎬 示例3 结合聊天交互模式，没有记忆能力，说完就忘
//        return args -> {
//            ChatClient chatClient = builder.build();
//            try (Scanner scanner = new Scanner(System.in)) {
//                while (true) {
//                    System.out.print("\n👨用户: ");
//                    System.out.println("\n🤖助手: " +
//                            chatClient.prompt(scanner.nextLine())
//                                    .call()
//                                    .content());
//                }
//            }
//        };

        //🎬 示例4 结合聊天交互模式，为模型增加记忆力，可以记住对话上下文。
//        return args -> {
//            String conversationId = "conversationId";//会话ID，用于识别不同的聊天
//            //创建基于内存（Map）的聊天记忆
//            InMemoryChatMemory inMemoryChatMemory = new InMemoryChatMemory();
//            //可以设置初始记忆，下面一行不是必须
//            inMemoryChatMemory.add(conversationId, List.of(new UserMessage("我叫刘海刚")));
//
//            ChatClient chatClient = builder
//                    //这里使用的内存记忆，重启后会消失。支持很多图/向量数据库来代替、持久记忆。
//                    .defaultAdvisors(new MessageChatMemoryAdvisor(inMemoryChatMemory))
//                    .build();
//
//            try (Scanner scanner = new Scanner(System.in)) {
//                while (true) {
//                    System.out.print("\n👨用户: ");
//                    System.out.println("\n🤖️助手: " +
//                            chatClient.prompt(scanner.nextLine())
//                                    //此处指定要进行对话的会话ID
//                                    .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY,conversationId)
//                                            //最大返回的记忆记录数，默认为100
////                                            .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY,100)
//                                            )
//                                    .call()
//                                    .content());
//                }
//            }
//        };

        //🎬 示例5 结合聊天交互模式，为模型增加记忆力，装配可用工具，工具定义配置文件：mcp-servers.json
        return args -> {
            ChatClient chatClient = builder
                    .defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory()))
                    //这里装配可用的工具
                    .defaultTools(new SyncMcpToolCallbackProvider(mcpClients))
                    .build();

            try (Scanner scanner = new Scanner(System.in)) {
                while (true) {
                    System.out.print("\n👨用户: ");
                    System.out.println("\n🤖️助手: " +
                            chatClient.prompt(scanner.nextLine())
                                    .call()
                                    .content());
                }
            }
        };
    }


}